import { Injectable, NotFoundException } from '@nestjs/common';
import { MongodbService } from '~/shared/mongodb/mongodb.service';
import { Types, isValidObjectId, PipelineStage } from 'mongoose';
import { Product, ProductStatus } from '~/shared/mongodb/schema/product.schema';
import {
  CreateProductDto,
  UpdateProductDto,
  QueryProductDto,
} from './product.dto';
import { paginate, Pagination, paginateAggregate } from '~/helper/paginate';
import { BusinessException } from '../../../common/exceptions/business.exception';
import { ErrorEnum } from '../../../constants/error-code.constant';

@Injectable()
export class ProductService {
  constructor(private readonly mongodbService: MongodbService) {}

  /**
   * 创建新商品
   */
  async create(createProductDto: CreateProductDto): Promise<Product> {
    // 1. 先验证categoryId格式是否正确
    if (!isValidObjectId(createProductDto.categoryId)) {
      throw new BusinessException(ErrorEnum.INVALID_ID_FORMAT);
    }

    const categoryObjectId = new Types.ObjectId(createProductDto.categoryId);

    const isExist = await this.mongodbService.CategoryModel.exists({
      _id: categoryObjectId,
    });

    if (!isExist) {
      throw new BusinessException(ErrorEnum.CATEGORY_NOT_EXIST);
    }

    const productData = {
      ...createProductDto,
      categoryId: categoryObjectId, // 确保存入的是ObjectId类型
    };

    const createdProduct = new this.mongodbService.ProductModel(productData);
    return createdProduct.save();
  }

  /**
   * 分页查询商品列表
   */
  async findAll(queryDto: QueryProductDto): Promise<Pagination<Product>> {
    // 1. 构建聚合管道
    const pipeline: PipelineStage[] = [];

    // 2. 匹配条件阶段（筛选商品）
    const matchStage: PipelineStage.Match = { $match: {} };

    // 商品名称模糊查询
    if (queryDto.name) {
      matchStage.$match.name = { $regex: queryDto.name, $options: 'i' };
    }

    // 分类筛选
    if (queryDto.categoryId) {
      // 使用 $expr 包裹聚合表达式
      matchStage.$match.$expr = {
        $eq: [
          '$categoryId', // 文档中的 categoryId 字段（假设是 ObjectId 类型）
          { $toObjectId: queryDto.categoryId }, // 将输入的字符串转换为 ObjectId
        ],
      };
    }

    // 状态筛选
    if (queryDto.status) {
      matchStage.$match.status = queryDto.status;
    }

    pipeline.push(matchStage);

    // 3. 关联分类集合，获取分类名称
    pipeline.push({
      $lookup: {
        from: 'category', // 分类集合名称（与分类schema的collection一致）
        localField: 'categoryId', // 商品集合中关联的字段
        foreignField: '_id', // 分类集合中被关联的字段
        as: 'categoryInfo', // 关联结果的别名
      },
    });

    // 4. 处理关联结果（取第一个元素，因为是一对一关联）
    pipeline.push({
      $addFields: {
        categoryInfo: { $arrayElemAt: ['$categoryInfo', 0] }, // 将数组转为对象
      },
    });

    // 5. 提取分类名称（处理可能的空值）
    pipeline.push({
      $addFields: {
        categoryName: { $ifNull: ['$categoryInfo.classifyname', null] },
        statusName: {
          $switch: {
            branches: [
              { case: { $eq: ['$status', 'on_sale'] }, then: '在售' },
              { case: { $eq: ['$status', 'off_sale'] }, then: '下架' },
            ],
            default: '未知状态', // 匹配不到任何case时的默认值
          },
        },
      },
    });

    // 6. 移除不需要的字段
    pipeline.push({
      $project: {
        __v: 0, // 排除版本字段
        // categoryInfo: 0, // 移除临时关联信息
      },
    });

    // 7. 排序阶段
    if (queryDto.sort) {
      switch (queryDto.sort) {
        case 'new':
          pipeline.push({
            $sort: { createdAt: -1 },
          });
          break;
        case 'priceAsc':
          pipeline.push({
            $sort: { sellingPrice: 1 },
          });
          break;
        case 'priceDesc':
          pipeline.push({
            $sort: { sellingPrice: -1 },
          });
          break;
        default:
          pipeline.push({
            $sort: { createdAt: -1 },
          });
      }
    }

    // console.log('聚合管道:', JSON.stringify(pipeline, null, 2));

    // 8. 执行分页聚合查询
    return paginateAggregate(this.mongodbService.ProductModel, pipeline, {
      page: queryDto.page,
      pageSize: queryDto.pageSize,
    });
  }

  /**
   * 查询单个商品详情（聚合管道实现，替换populate）
   */
  async findOne(id: string): Promise<Product & { categoryName: string }> {
    // 验证ID格式
    if (!isValidObjectId(id)) {
      throw new BusinessException(ErrorEnum.INVALID_ID_FORMAT);
    }

    // 构建聚合管道
    const pipeline: PipelineStage[] = [
      // 匹配指定ID的商品
      { $match: { _id: new Types.ObjectId(id) } },

      // 关联分类集合
      {
        $lookup: {
          from: 'category', // 分类集合名称
          localField: 'categoryId',
          foreignField: '_id',
          as: 'categoryInfo',
        },
      },

      // 提取分类信息（处理一对一关联）
      { $addFields: { categoryInfo: { $arrayElemAt: ['$categoryInfo', 0] } } },

      // 提取分类名称，默认"未知分类"
      {
        $addFields: {
          categoryName: { $ifNull: ['$categoryInfo.classifyname', '未知分类'] },
          statusName: {
            $switch: {
              branches: [
                { case: { $eq: ['$status', 'on_sale'] }, then: '在售' },
                { case: { $eq: ['$status', 'off_sale'] }, then: '预售' },
              ],
              default: '未知状态', // 匹配不到任何case时的默认值
            },
          },
        },
      },

      // 移除不需要的字段
      { $project: { __v: 0, categoryInfo: 0 } },
    ];

    // 执行聚合查询
    const result = await this.mongodbService.ProductModel.aggregate<
      Product & { categoryName: string }
    >(pipeline).exec();

    // 检查商品是否存在
    if (result.length === 0) {
      throw new BusinessException(ErrorEnum.PRODUCT_NOT_EXIST);
    }

    return result[0];
  }

  /**
   * 更新商品信息
   */
  async update(id: string, updateProductDto: UpdateProductDto) {
    // 验证ID格式
    if (!isValidObjectId(id) || !isValidObjectId(updateProductDto.categoryId)) {
      throw new BusinessException(ErrorEnum.INVALID_ID_FORMAT);
    }
    const categoryObjectId = new Types.ObjectId(updateProductDto.categoryId);
    const isExist = await this.mongodbService.CategoryModel.exists({
      _id: categoryObjectId,
    });

    if (!isExist) {
      throw new BusinessException(ErrorEnum.CATEGORY_NOT_EXIST);
    }

    // 先执行更新操作
    const updatedProduct =
      await this.mongodbService.ProductModel.findByIdAndUpdate(
        id,
        {
          ...updateProductDto,
          categoryId: new Types.ObjectId(updateProductDto.categoryId),
        },
        { new: true, runValidators: true },
      ).exec();

    // 检查商品是否存在
    if (!updatedProduct) {
      throw new BusinessException(ErrorEnum.PRODUCT_NOT_EXIST);
    }

    return { msg: '更新成功' };
  }

  //是否设置为热门
  async setHotById(id: string, isHot: boolean) {
    // 验证ID格式
    if (!isValidObjectId(id) || !isValidObjectId(id)) {
      throw new BusinessException(ErrorEnum.INVALID_ID_FORMAT);
    }

    // 先执行更新操作
    const updatedProduct =
      await this.mongodbService.ProductModel.findByIdAndUpdate(
        id,
        {
          isHot: isHot,
        },
        { new: true, runValidators: true },
      ).exec();

    // 检查商品是否存在
    if (!updatedProduct) {
      throw new BusinessException(ErrorEnum.PRODUCT_NOT_EXIST);
    }

    return { msg: '设置成功' };
  }
  /**
   * 删除商品
   */
  async remove(id: string) {
    const result = await this.mongodbService.ProductModel.deleteOne({
      _id: id,
    }).exec();

    if (result.deletedCount === 0) {
      throw new BusinessException(ErrorEnum.PRODUCT_NOT_EXIST);
    }
    return { msg: '删除成功' };
  }
}
